package sat.component;

import java.util.LinkedList;
import java.util.List;

import org.mt4j.MTApplication;
import org.mt4j.components.visibleComponents.font.FontManager;
import org.mt4j.components.visibleComponents.shapes.MTPolygon;
import org.mt4j.components.visibleComponents.shapes.MTRoundRectangle;
import org.mt4j.components.visibleComponents.widgets.MTTextField;
import org.mt4j.input.gestureAction.TapAndHoldVisualizer;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.tapAndHoldProcessor.TapAndHoldEvent;
import org.mt4j.input.inputProcessors.componentProcessors.tapAndHoldProcessor.TapAndHoldProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapProcessor;
import org.mt4j.util.MTColor;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;

import sat.frame.WorkPlaceScene;
import sat.model.UseCaseModel;

// this class does not extend UMLEntity, because its shape is oval
public class UseCaseAssociationComponent extends MTRoundRectangle{

	private static final float width = 150;
	private static final float height = 100;
	private static final float textWidth = 80;
	private static final float textHeight = 50;
	private static final float cornerRadius = 50;
	private static final int fontsize = 15;
	private MTTextField actionField;
	
	private boolean tappable = true;
	
	private UseCaseAssociationComponent instance;
	
	private UseCaseComponentPopUp popup;

	private UseCaseModel model;
	
	private  Vector3D pos = null;

	private DragAndDropButton linkButton;
	
	private MTPolygon currentComponentHovered;
	
	private MTPolygon lastComponentHoverred;
	

	private List<Link> linkList = new LinkedList<Link>();  

	public List<Link> getLinkList() {
		return linkList;
	}

	public void addLinkToList(Link l){
		linkList.add(l);
	}
	
	//refresh interface view
	public void refreshView(String content){
		actionField.setText(content);
	}
	
	public void showPopUp(){
		popup.setVisible(true);
		popup.setPositionRelativeToParent(new Vector3D(width*2+30,height/2));
	}
	
	public UseCaseAssociationComponent(final MTApplication mtApplication){
		super(mtApplication, 0, 0, 0, width, height, cornerRadius+20, cornerRadius);
		this.setFillColor(new MTColor(215, 195, 168, 255));
		this.setStrokeColor(new MTColor(56, 62, 52, 255));
		this.setStrokeWeight(3);
		
		model = new UseCaseModel(this,null);
		popup = new UseCaseComponentPopUp(mtApplication,model);
		
		instance = this;
		
		actionField = new MTTextField(mtApplication, 0, 0, textWidth, textHeight, 
				FontManager.getInstance().createFont(mtApplication, "Comic Sans MS",
						fontsize, // Font size
						new MTColor(56, 62, 52, 255), // Font fill color
						true));
		
		actionField.setPositionRelativeToParent(new Vector3D(width/2,height/2));
		actionField.setNoFill(true);
		actionField.setNoStroke(true);
		actionField.setPickable(false);
		
		this.addChild(actionField);
		this.addChild(popup);
		
		//gesture for pop-up
		this.registerInputProcessor(new TapProcessor(mtApplication));
		this.addGestureListener(TapProcessor.class, new IGestureEventListener() {
			@Override
			public boolean processGestureEvent(MTGestureEvent ge) {
				// TODO Auto-generated method stub
				TapEvent te = (TapEvent)ge;
				if(instance.tappable){
					switch (te.getTapID()) {
					case TapEvent.TAPPED:
						System.out.println("Tapped");
						showPopUp();
						break;
					default:
						break;
					}
				}
				else
					tappable = true;
				return false;
			}
		});
		
		//gesture for deleting
		this.addGestureListener(TapAndHoldProcessor.class, new TapAndHoldVisualizer(mtApplication, this));
		this.registerInputProcessor(new TapAndHoldProcessor(mtApplication,1500));
		this.addGestureListener(TapAndHoldProcessor.class, new IGestureEventListener() {
			@Override
			public boolean processGestureEvent(MTGestureEvent ge) {
				TapAndHoldEvent e = (TapAndHoldEvent)ge;
				if (e.getId() == TapAndHoldEvent.GESTURE_ENDED && e.isHoldComplete()){
					System.out.println("start");
					e.stopPropagation();
					tappable = false;
					instance.destroy();
				}
				return false;
			}
		});
		
		linkButton = new DragAndDropButton(mtApplication,DragAndDropButton.ButtonType.LINK,"link.png");
		this.addChild(linkButton);
		linkButton.setPositionRelativeToParent(new Vector3D(-20,-20));

		//linkButton.removeAllGestureEventListeners();

		linkButton.addGestureListener(DragProcessor.class,new IGestureEventListener() {
			public boolean processGestureEvent(MTGestureEvent evt) {

				DragEvent de = (DragEvent) evt;
				switch (de.getId()) {
				case MTGestureEvent.GESTURE_STARTED:
					pos = new Vector3D(linkButton.getCenterPointRelativeToParent());
					break;
				case MTGestureEvent.GESTURE_UPDATED:
					System.out.println("updating");
					currentComponentHovered = WorkPlaceScene.getInstance().findUseCaseAssociationComponentByPosition(linkButton.getCenterPointGlobal());
					System.out.println(currentComponentHovered);
					if(currentComponentHovered != null && currentComponentHovered != instance){
						
						// highlight the current class hovered
						currentComponentHovered.setStrokeColor(MTColor.GREEN);
						currentComponentHovered.setNoStroke(false);
						currentComponentHovered.setStrokeWeight(10);
						lastComponentHoverred = currentComponentHovered;
					}
					else if (lastComponentHoverred != null)
						lastComponentHoverred.setNoStroke(true);
					break;
				case MTGestureEvent.GESTURE_ENDED:
					MTPolygon componentDroppedOn =  WorkPlaceScene.getInstance().findUseCaseAssociationComponentByPosition(linkButton.getCenterPointGlobal());
					if(componentDroppedOn != null && componentDroppedOn instanceof UseCaseAssociationComponent){
						Link l = new Link(mtApplication,instance,componentDroppedOn);
						
						instance.addLinkToList(l);
						((UseCaseAssociationComponent)componentDroppedOn).addLinkToList(l);
						WorkPlaceScene.getInstance().getCanvas().addChild(l.getLinkLine()); // add the link on the canvas
						componentDroppedOn.setNoStroke(true);
					}
					System.out.println("the component catches is = "+componentDroppedOn);
					linkButton.setPositionRelativeToParent(pos);
					break;
				default:
					break;
				}
				return false;
			}

		});
		
		this.addGestureListener(DragProcessor.class, new IGestureEventListener() {
			@Override
			public boolean processGestureEvent(MTGestureEvent evt) {
				// TODO Auto-generated method stub
				DragEvent de = (DragEvent) evt;
				switch (de.getId()) {
				case MTGestureEvent.GESTURE_STARTED:
					break;
				case MTGestureEvent.GESTURE_UPDATED:

					for (int i = 0; i < linkList.size(); i++) {
						Vertex[] v = new Vertex[]{
								new Vertex(instance.getCenterPointGlobal().x,instance.getCenterPointGlobal().y),
								new Vertex(linkList.get(i).getLinkLine().getEntity2() == instance ? linkList.get(i).getLinkLine().getEntity1Centre() : 
									linkList.get(i).getLinkLine().getEntity2Centre())
						};
						linkList.get(i).getLinkLine().setVertices(v);
					}
					break;
				case MTGestureEvent.GESTURE_ENDED:
					break;
				default:
					break;
				}
				return false;
			}

		});
		
		this.addGestureListener(TapAndHoldProcessor.class, new IGestureEventListener() {
			@Override
			public boolean processGestureEvent(MTGestureEvent ge) {
				TapAndHoldEvent e = (TapAndHoldEvent)ge;
				if (e.getId() == TapAndHoldEvent.GESTURE_ENDED && e.isHoldComplete()){
					for (int i = 0; i < linkList.size(); i++) {
						linkList.get(i).getLinkLine().destroy();
					}
					instance.destroy();
				}
				return false;
			}
		});
	}
}
